<?php

namespace App\Kuafu\User\Service;

use App\Exceptions\BaseException;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Feishu\Model\FsUserModel;
use App\Kuafu\Feishu\Service\SsoService;
use App\Kuafu\Log\Service\UserLoginLogService;
use App\Kuafu\User\Enum\CodeEnum;
use App\Kuafu\User\Enum\UserCacheEnum;
use App\Kuafu\User\Enum\UserCodeEnum;
use App\Kuafu\User\Exceptions\AuthException;
use App\Kuafu\User\Exceptions\UserException;
use App\Kuafu\User\Model\Permissions;
use App\Kuafu\User\Model\RolePermissionMappings;
use App\Kuafu\User\Model\User;
use App\Library\KfHttp\TigerCurl;
use App\Remote\Feishu\Sso\SsoRemote;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Facades\Cache;
use Psr\SimpleCache\InvalidArgumentException;

class AuthService extends BaseService
{
    /**
     * 注册
     * @param $request
     * @return array
     * @throws UserException
     */
    public static function register($request)
    {
        try {
            UserService::save($request);
        } catch (\Throwable $e) {
            throw new UserException(UserCodeEnum::ERR_USER_INSERT, '', $e);
        }
    }

    /**
     * 登录
     * @param $request
     * @param $type
     * @param int $isLasting
     * @return bool
     * @throws UserException
     */
    public static function login(
        $request,
        $type,
        $isLasting = 0,
        $longitude = '',
        $latitude = '',
        $serialNumber = '',
        string $formIp = ''
    ) {
        $ip = $formIp ?: (string)$request->ip();

        $input = $request->only('username', 'password');
        $field = ['salt', 'status', 'id', 'username', 'mobile'];
        if (preg_match("/^1[3456789]\d{9}$/", $input['username'])) {
            $input['mobile'] = $input['username'];
            unset($input['username']);
            $userInfo = UserService::getUserValue('mobile', $input['mobile'], $field);
        } else {
            $userInfo = UserService::getUserValue('username', $input['username'], $field);
        }
        if (!$userInfo) {
            throw new UserException(UserCodeEnum::ERR_USER_NOT_EXIST);
        }
        if ($userInfo['status'] == CodeEnum::USER_STATUS_STOP) {
            throw new UserException(UserCodeEnum::ERR_USER_STATUS_STOP);
        }
        $input['password'] = $input['password'] . $userInfo['salt'];

        if ($isLasting) {
            if (!$jwt_token = auth('api')->setttl(CodeEnum::KEEP_LOGIN_TIME)
                                         ->claims(['type' => UserCodeEnum::CODE_TEXT[$type], 'ip' => $ip])
                                         ->attempt($input)) {
                throw new UserException(UserCodeEnum::ERR_USER_PASSWORD);
            }
        } else {
            if (!$jwt_token = auth('api')->claims(['type' => UserCodeEnum::CODE_TEXT[$type], 'ip' => $ip])
                                         ->attempt($input)) {
                throw new UserException(UserCodeEnum::ERR_USER_PASSWORD);
            }
        }

        //记录操作日志
        UserLoginLogService::addUserLoginLog($userInfo['id'], $type, $longitude, $latitude, $serialNumber,
            $userInfo['mobile'], $userInfo['username'], $ip);
        return config('jwt.JWT_PREFIX') . ' ' . $jwt_token;
    }

    /**
     * 退出登录
     * @throws UserException
     */
    public static function logout()
    {
        try {
            auth('api')->logout();
        } catch (\Exception $exception) {
            throw new UserException(UserCodeEnum::ERR_SERVER_ERROR, '', $exception);
        }
    }

    /**
     * 获取用户信息
     */
    private static $userInfo;


    /**
     * @return Authenticatable|null
     * @throws UserException
     */
    public static function getAuthUser(): ?Authenticatable
    {
        try {
            if (empty(self::$userInfo)) {
                self::$userInfo = auth('api')->user();
                if (!self::$userInfo) {
                    throw new UserException(UserCodeEnum::ERR_USER_NOT_EXIST);
                }
            }
            return self::$userInfo;
        } catch (\Exception $exception) {
            throw new UserException(UserCodeEnum::ERR_USER_NOT_EXIST, '', $exception);
        }
    }

    /**
     * 获取用户载体信息
     * @return mixed
     */
    public static function getPayload()
    {
        try {
            return auth('api')->payload();
        } catch (\Exception $exception) {
            throw new AuthException(UserCodeEnum::ERR_USER_PAYLOAD, '', $exception);
        }

    }

    /**
     * 刷新 token
     */
    public static function refresh()
    {
        try {
            $token = auth('api')->refresh();
            return config("jwt.JWT_PREFIX") . ' ' . $token;
        } catch (\Exception $exception) {
            throw new AuthException(BaseCodeEnum::ERR_TOKEN_ERROR, '');
        }
    }

    /**
     * 加入黑名单
     */
    public static function invalidate()
    {
        try {
            auth('api')->invalidate();
        } catch (\Exception $exception) {
            throw new AuthException($exception->getCode(), $exception->getMessage(), $exception);
        }
    }

    /**
     * 获取用户id
     */
    public static function getUserId(bool $throwError = true): int
    {
        try {
            $userInfo = self::getAuthUser();
            return $userInfo['id'];
        } catch (\Exception $exception) {
            if ($throwError) {
                throw new UserException(UserCodeEnum::ERR_USER_NOT_EXIST, '', $exception);
            } else {
                return 0;
            }
        }
    }

    /**
     * 获取用户名字
     */
    public static function getUserInfo(string $param, bool $throwError = true)
    {
        try {
            $userInfo = self::getAuthUser();
            return $userInfo[$param];
        } catch (\Exception $exception) {
            if ($throwError) {
                throw new UserException(UserCodeEnum::ERR_USER_NOT_EXIST, '', $exception);
            } else {
                return '';
            }
        }
    }

    /**
     * 手机号登录
     * @param $mobile
     * @return array|mixed
     */
    public static function mobileLogin(
        $mobile,
        $type,
        $isLasting,
        $ip = '',
        $longitude = '',
        $latitude = '',
        $serialNumber = ''
    ) {
        $longitude    = $request->longitude ?? '';
        $latitude     = $request->latitude ?? '';
        $serialNumber = $request->serialNumber ?? '';

        $user = User::query()->where('mobile', '=', $mobile)->first();
        if ($user) {
            //检查用户状态
            if ($user['status'] == CodeEnum::USER_STATUS_STOP) {
                throw new UserException(UserCodeEnum::ERR_USER_STATUS_STOP);
            }
            //获取token
            if ($isLasting) {
                if (!$jwt_token = auth('api')->setttl(CodeEnum::KEEP_LOGIN_TIME)
                                             ->claims(['type' => UserCodeEnum::CODE_TEXT[$type], 'ip' => $ip])
                                             ->login($user)) {
                    throw new UserException(UserCodeEnum::ERR_USER_PASSWORD);
                }
            } else {
                if (!$jwt_token = auth('api')->claims(['type' => UserCodeEnum::CODE_TEXT[$type], 'ip' => $ip])
                                             ->login($user)) {
                    throw new UserException(UserCodeEnum::ERR_USER_PASSWORD);
                }
            }

            // 记录操作日志
            UserLoginLogService::addUserLoginLog($user->id, $type, $longitude, $latitude, $serialNumber, $user->mobile,
                $user->username, $ip);

            return config('jwt.JWT_PREFIX') . ' ' . $jwt_token;
        } else {
            throw new AuthException(UserCodeEnum::ERR_USER_NOT_EXIST);
        }
    }

    /**
     * 获取所有权限列表
     *
     * @param int $userId
     * @param int $brandId
     * @param int $shopId
     * @return array
     * @throws \App\Kuafu\User\Exceptions\UserRoleException
     */
    public static function getUserAllWebPermission(int $userId, int $brandId, int $shopId)
    {
        // 获取角色列表
        $roleList = UserRoleService::getWebUserRoleList($userId, $brandId, $shopId);

        // 获取角色的所有权限列表
        $rolePermissionIdsAll = RolePermissionMappings::getAllByRoleList($roleList)->pluck('permissionId')
                                                      ->toArray();

        $rolePermissionIdsAll = Permissions::getAllByIds($rolePermissionIdsAll,
            \App\Kuafu\Common\Enum\CodeEnum::PLATFORM_B_BRAND)
                                           ->pluck('action')->map(function ($value) {
                return strtolower($value);
            })->toArray();

        return $rolePermissionIdsAll;
    }

    /**
     * @param string $code
     * @param int $appType
     * @return string
     * @throws AuthException
     * @throws UserException
     * @throws BaseException
     * @throws GuzzleException
     * @throws InvalidArgumentException
     */
    public static function fsLogin(string $code, int $appType, string $ip = ''): string
    {
        $ssoUserinfo = SsoRemote::userinfo($appType, $code);
//        $ssoUserinfo = json_decode('
//        {
//        "sub": "ou_67e561f38af0011fc3ec366459762fbb",
//        "picture": "https://s3-imfile.feishucdn.com/static-resource/v1/v2_bd1d158a-1091-4c3a-a74d-62a0c70cf0eg~?image_size=72x72&cut_type=&quality=&format=png&sticker_format=.webp",
//        "name": "王晓东",
//        "en_name": "",
//        "tenant_key": "13a5aac7558d5740",
//        "avatar_url": "https://s3-imfile.feishucdn.com/static-resource/v1/v2_bd1d158a-1091-4c3a-a74d-62a0c70cf0eg~?image_size=72x72&cut_type=&quality=&format=png&sticker_format=.webp",
//        "avatar_thumb": "https://s3-imfile.feishucdn.com/static-resource/v1/v2_bd1d158a-1091-4c3a-a74d-62a0c70cf0eg~?image_size=72x72&cut_type=&quality=&format=png&sticker_format=.webp",
//        "avatar_middle": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_bd1d158a-1091-4c3a-a74d-62a0c70cf0eg~?image_size=240x240&cut_type=&quality=&format=png&sticker_format=.webp",
//        "avatar_big": "https://s1-imfile.feishucdn.com/static-resource/v1/v2_bd1d158a-1091-4c3a-a74d-62a0c70cf0eg~?image_size=640x640&cut_type=&quality=&format=png&sticker_format=.webp",
//        "open_id": "ou_0d543313f48d9701fb4fd47b88b050aa",
//        "union_id": "ou_f79d46136956f65f16a64d427aa50faa",
//        "user_id": "c4gc4446",
//        "employee_no": "0435",
//        "mobile": "+8618827529063"
//    }', true);
        $openId = $ssoUserinfo["open_id"];
        $fsUser = FsUserModel::query()->where("openId", $openId)->first();
        $user   = User::query()->where("mobile", $fsUser->mobile)->first();
        if ($user) {
            //检查用户状态
            if ($user['status'] == CodeEnum::USER_STATUS_STOP) {
                throw new UserException(UserCodeEnum::ERR_USER_STATUS_STOP);
            }

            if (
                !($jwt_token = auth('api')
                    ->setttl(CodeEnum::KEEP_LOGIN_TIME)
                    ->claims([
                        "type"           => UserCodeEnum::CODE_TEXT[$appType],
                        "thirdLoginType" => "fs",
                        "ip"             => $ip,
                    ])->login($user))
            ) {
                throw new UserException(UserCodeEnum::ERR_USER_PASSWORD);
            }

            //记录操作日志
            UserLoginLogService::addUserLoginLog($user->id, $appType, '', '', '',
                $user->mobile, $user->username, $ip);

            return config('jwt.JWT_PREFIX') . ' ' . $jwt_token;
        } else {
            throw new AuthException(UserCodeEnum::ERR_USER_NOT_EXIST);
        }
    }


    /**
     * 解析 JWT
     *
     * @return array
     */
    public static function decodeJwt(): array
    {
        return [
            'payload' => auth('api')->payload(),
            'user'    => auth('api')->user()
        ];
    }
}
